package com.yeskery.nut.extend.redis;

import com.yeskery.nut.application.ServerEventContext;
import com.yeskery.nut.plugin.NutApplicationSupportBasePlugin;
import com.yeskery.nut.plugin.PluginBeanMetadata;
import com.yeskery.nut.plugin.ServerEventPlugin;
import com.yeskery.nut.util.StringUtils;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.cluster.ClusterClientOptions;

import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Lettuce插件 For Redis
 * @author Yeskery
 * 2023/8/15
 */
public class LettucePlugin extends NutApplicationSupportBasePlugin implements ServerEventPlugin {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(LettucePlugin.class.getName());

    /** 默认超时时间 */
    private static final int DEFAULT_TIME_OUT = 10;

    /** Lettuce Client对象 */
    private final RedisClient redisClient;

    /** 字符串连接对象 */
    private final StatefulRedisConnection<String, String> stringConnection;

    /**
     * 构建一个Lettuce插件
     * @param host 主机
     * @param port 端口号
     * @param password 密码
     * @param database 数据库序号
     * @param timeout 超时时间
     */
    public LettucePlugin(String host, int port, String password, int database, int timeout) {
        RedisURI.Builder builder = RedisURI.builder();
        builder.withHost(host).withPort(port).withDatabase(database);
        if (!StringUtils.isEmpty(password)) {
            builder.withPassword(password.toCharArray());
        }
        builder.withTimeout(Duration.of(timeout, ChronoUnit.SECONDS));
        redisClient = RedisClient.create(builder.build());

        ClusterClientOptions options = ClusterClientOptions.builder()
                .autoReconnect(true)
                .pingBeforeActivateConnection(true)
                .validateClusterNodeMembership(true)
                .build();
        redisClient.setOptions(options);
        stringConnection = redisClient.connect();
    }

    /**
     * 构建一个Lettuce插件
     * @param host 主机
     * @param port 端口号
     * @param password 密码
     */
    public LettucePlugin(String host, int port, String password) {
        this(host, port, password, 0, DEFAULT_TIME_OUT);
    }

    /**
     * 构建一个Lettuce插件
     * @param host 主机
     * @param port 端口号
     */
    public LettucePlugin(String host, int port) {
        this(host, port, null);
    }

    /**
     * 构建一个Lettuce插件
     */
    public LettucePlugin() {
        this("127.0.0.1", 6379);
    }

    @Override
    protected Collection<PluginBeanMetadata> getRegisterPluginBeanMetadata() {
        return Arrays.asList(new PluginBeanMetadata("redisClient", redisClient, RedisClient.class),
                new PluginBeanMetadata("stringConnection", stringConnection, StatefulRedisConnection.class));
    }

    @Override
    public void beforeClose(ServerEventContext serverEventContext) {
        try {
            stringConnection.close();
        } catch (Exception e) {
            logger.logp(Level.SEVERE, this.getClass().getName(), "beforeClose",
                    "Lettuce Connection Close Fail.", e);
        }
        try {
            redisClient.shutdown();
        } catch (Exception e) {
            logger.logp(Level.SEVERE, this.getClass().getName(), "beforeClose",
                    "Lettuce Redis Client Shutdown Fail.", e);
        }
    }
}
